﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using SmartMeterParamFrame.Connection;

namespace SmartMeterParamFrame
{
    public partial class Communicate
    {
        /// <summary>
        /// 同时开多少个线程
        /// </summary>
        int threadCount = 1;
        /// <summary>
        /// 一个通道带的表位数
        /// </summary>
        int oneChannelBws = 1;
        /// <summary>
        /// 开启线程需要循环的次数
        /// </summary>
        int threadWhileCount = 1;

        System.Threading.Tasks.Task[] threadMethod;


        /// <summary>
        /// 初始化线程信息
        /// </summary>
        private void InitThreadInfo()
        {
            oneChannelBws = DeviceControl.Bws / DeviceControl.BusCount;

            if (DeviceControl.ThreadCount > DeviceControl.BusCount)
            {
                threadCount = DeviceControl.BusCount;
            }
            else
            {
                threadCount = DeviceControl.ThreadCount;
            }

            threadMethod = new System.Threading.Tasks.Task[threadCount];

            threadWhileCount = DeviceControl.BusCount / threadCount + (DeviceControl.BusCount % threadCount == 0 ? 0 : 1);      //线程需要循环的次数
        }

        private void Star(Model.FAinfo Item, Func<string, bool> CallBackKeyDownStepFunction = null)
        {
            int nowChannelID = 0;

            int intDownKeyStep = 0;         //下装计数器

            while (true)
            {
                if (isAbort) break;
                for (int i = 0; i < threadWhileCount; i++)
                {
                    if (isAbort) break;
                    for (int b = 0; b < oneChannelBws; b++)     //一个通道内表位循环
                    {
                        if (isAbort) break;
#if !DEBUG
                        if (!DeviceControl.IsChannnelConst) //关闭所有误差板
                        {
                            DeviceControl.SetWcb(0xFF, false);
                            Thread.Sleep(UDPClient.WcbDelay);
                            DeviceControl.SetWcb(0xFF, false);
                            Thread.Sleep(UDPClient.WcbDelay);
                        }
                        else
                        {
                            DeviceControl.SetWcb(b + 1, true);//打开每一个通道内对应的 第b+1个485通道
                            Thread.Sleep(UDPClient.WcbDelay);
                            DeviceControl.SetWcb(b + 1, true);
                            Thread.Sleep(UDPClient.WcbDelay);
                        }
#endif
                        for (int j = 0; j < threadCount; j++)
                        {
                            if (isAbort) break;
                            nowChannelID = threadCount * i + j + 1;     //当前通道号
                            if (nowChannelID > DeviceControl.BusCount) continue;   //如果当前通道号大于总通道数量则跳过
                            int bwh = oneChannelBws * (nowChannelID - 1) + b;       //当前表位号
                            if (!MeterItems[bwh].CheckYn || (MeterItems[bwh].IsFailed && MeterItems[bwh].getPrjResult(Item.PrjOrderID, true) != EnumResult.失败) || MeterItems[bwh].IsFaItemOk(Item.PrjOrderID))
                            {
                                threadMethod[j] = null;
                                continue;
                            }
                            if (!DeviceControl.IsChannnelConst)
                            {
#if !DEBUG
                                DeviceControl.SetWcb(bwh + 1, true);
                                Thread.Sleep(UDPClient.WcbDelay);
                                DeviceControl.SetWcb(bwh + 1, true);
                                Thread.Sleep(UDPClient.WcbDelay);
#endif
                            }
                            if (isAbort) break;
                            switch (Item.PrjType)
                            {
                                case EnumFAType.其他操作:
                                case EnumFAType.一类参数:
                                case EnumFAType.二类参数:
                                    threadMethod[j] = new System.Threading.Tasks.Task(new Action(() =>
                                                        {
                                                            #region -----------------------操作业务------------------------
                                                            bool reviewResult = true;
                                                            bool setResult = true;
                                                            bool isReviewed = false;
                                                            bool isWrited = false;

                                                            //第一步，复核
                                                            if (Item.ReviewType == EnumCheckType.复核修正 || Item.ReviewType == EnumCheckType.复核修正复核 ||
                                                                 Item.ReviewType == EnumCheckType.仅复核)
                                                            {
                                                                isReviewed = true;
                                                                MeterItems[bwh].SetPrjResult(Item.PrjOrderID, EnumResult.进行中, true);
                                                                reviewResult = MeterItems[bwh].MControl.ReviewParam(this.DeviceControl.SendData, Item.BsCode, Item.DataDomain);
                                                                if (reviewResult)
                                                                {
                                                                    MeterItems[bwh].SetPrjResult(Item.PrjOrderID, EnumResult.成功, true);           //如果复核成功，就直接退出，不需要再继续写
                                                                }
                                                                else
                                                                {
                                                                    MeterItems[bwh].SetPrjResult(Item.PrjOrderID, EnumResult.失败, true);
                                                                }
                                                            }
                                                            //第二步，需要修正，且复核没有成功
                                                            if ((Item.ReviewType == EnumCheckType.仅修正 ||
                                                                Item.ReviewType == EnumCheckType.复核修正 ||
                                                                Item.ReviewType == EnumCheckType.复核修正复核 ||
                                                                Item.ReviewType == EnumCheckType.修正复核) &&
                                                                ((isReviewed == false) || (isReviewed == true && reviewResult == false)))
                                                            {
                                                                isWrited = true;
                                                                MeterItems[bwh].SetPrjResult(Item.PrjOrderID, EnumResult.进行中, false);
                                                                int icount = 0;
                                                                while (icount < 4)
                                                                {
                                                                    if (isAbort) break;
                                                                    if (Item.PrjType == EnumFAType.其他操作)
                                                                    {
                                                                        setResult = MeterItems[bwh].MControl.SetStandardParam(this.DeviceControl.SendData,
                                                                                                                                       meterpwd,
                                                                                                                                       meterlevel,
                                                                                                                                       Item.BsCode,
                                                                                                                                       Item.DataDomain);
                                                                    }
                                                                    else
                                                                    {
                                                                        setResult = MeterItems[bwh].MControl.SetClassParam(this.DeviceControl.SendData,
                                                                                                                                em.IdentityAuthentication,
                                                                                                                                em.getParameterUpdate,
                                                                                                                                em.getParameterElseUpdate,
                                                                                                                                Item.BsCode,
                                                                                                                                Item.DataDomain,
                                                                                                                                Item.PrjType == EnumFAType.一类参数 ? true : false);
                                                                    }
                                                                    if (setResult == true)
                                                                        break;
                                                                    icount++;
                                                                }
                                                                if (setResult == true)
                                                                {
                                                                    MeterItems[bwh].SetPrjResult(Item.PrjOrderID, EnumResult.成功, false);
                                                                }
                                                                else // 如果修正失败
                                                                {
                                                                    //如果是 二类参数且写失败，则自动使用密码进行编程
                                                                    if (Item.PrjType == EnumFAType.二类参数)
                                                                    {
                                                                        setResult = MeterItems[bwh].MControl.SetStandardParam(this.DeviceControl.SendData,
                                                                                                                                     meterpwd,
                                                                                                                                     meterlevel,
                                                                                                                                     Item.BsCode,
                                                                                                                                     Item.DataDomain);
                                                                    }
                                                                    MeterItems[bwh].SetPrjResult(Item.PrjOrderID, setResult ? EnumResult.成功 : EnumResult.失败, false);
                                                                }
                                                            }

                                                            //第三步，再次复核
                                                            if ((Item.ReviewType == EnumCheckType.复核修正复核 || Item.ReviewType == EnumCheckType.修正复核) &&
                                                                (isWrited == true && setResult == true))
                                                            {
                                                                MeterItems[bwh].SetPrjResult(Item.PrjOrderID, EnumResult.进行中, true);
                                                                reviewResult = MeterItems[bwh].MControl.ReviewParam(this.DeviceControl.SendData, Item.BsCode, Item.DataDomain);
                                                                MeterItems[bwh].SetPrjResult(Item.PrjOrderID, reviewResult ? EnumResult.成功 : EnumResult.失败, true);
                                                            }

                                                            #endregion
                                                        }));
                                    break;
                                case EnumFAType.费控功能:
                                    threadMethod[j] = new System.Threading.Tasks.Task(new Action(() =>
                                                        {
                                                            #region 操作业务
                                                            if (em == null)
                                                            {
                                                                MeterItems[bwh].CurrentDesc = "加密机尚未连接，无法完成操作";
                                                                return;
                                                            }

                                                            MeterItems[bwh].SetPrjResult(Item.PrjOrderID, EnumResult.进行中, false);

                                                            EnumUserControl control = (EnumUserControl)int.Parse(Item.DataDomain);

                                                            bool setResult = MeterItems[bwh].MControl.UserControlVir(control,
                                                                                                                   DeviceControl.SendData,
                                                                                                                   em.IdentityAuthentication,
                                                                                                                   em.getUserControl);

                                                            MeterItems[bwh].SetPrjResult(Item.PrjOrderID, setResult ? EnumResult.成功 : EnumResult.失败, setResult ? EnumResult.成功 : EnumResult.失败);
                                                            #endregion
                                                        }));
                                    break;
                                case EnumFAType.密钥下装:
                                    threadMethod[j] = new System.Threading.Tasks.Task(new Action(() =>
                                                        {
                                                            #region -----------------------操作业务------------------------
                                                            if (em == null)
                                                            {
                                                                MeterItems[bwh].CurrentDesc = "加密机尚未连接，无法完成操作";
                                                                return;
                                                            }

                                                            MeterItems[bwh].SetPrjResult(Item.PrjOrderID, EnumResult.进行中, true);

                                                            bool CheckResult = MeterItems[bwh].MControl.IdentityAuthentication(EnumKeyState.私钥状态, DeviceControl.SendData, em.IdentityAuthentication);

                                                            if (CheckResult)
                                                            {
                                                                MeterItems[bwh].SetPrjResult(Item.PrjOrderID, EnumResult.成功, EnumResult.成功);
                                                                return;
                                                            }


                                                            MeterItems[bwh].SetPrjResult(Item.PrjOrderID, EnumResult.进行中, EnumResult.失败);

                                                            bool setResult = false;
                                                            if (intDownKeyStep == 0)
                                                            {
                                                                MeterItems[bwh].MControl.IsYuanCheng = IsYuanCheng;
                                                                setResult = MeterItems[bwh].MControl.GotoFirstStep(DeviceControl.SendData,
                                                                                                                    em.IdentityAuthentication,
                                                                                                                    em.getClearKey);
                                                                if (!setResult)            //如果第一步都失败了，就不进入第二部
                                                                {
                                                                    MeterItems[bwh].SetPrjResult(Item.PrjOrderID, EnumResult.失败, EnumResult.失败);
                                                                }
                                                                else
                                                                {
                                                                    MeterItems[bwh].SetPrjResult(Item.PrjOrderID, EnumResult.成功, false);
                                                                }

                                                            }
                                                            else
                                                            {
                                                                setResult = MeterItems[bwh].MControl.GotoSecondStep(DeviceControl.SendData,
                                                                                                                  em.IdentityAuthentication,
                                                                                                                  em.getClearKey,
                                                                                                                  em.getUpdateKey);

                                                                if (!setResult)
                                                                {
                                                                    MeterItems[bwh].SetPrjResult(Item.PrjOrderID, EnumResult.失败, EnumResult.失败);
                                                                }
                                                                else
                                                                {
                                                                    MeterItems[bwh].SetPrjResult(Item.PrjOrderID, EnumResult.成功, EnumResult.进行中);
                                                                    bool checkResult = MeterItems[bwh].MControl.IdentityAuthentication(EnumKeyState.私钥状态,
                                                                                                                                  DeviceControl.SendData,
                                                                                                                                  em.IdentityAuthentication);
                                                                    MeterItems[bwh].SetPrjResult(Item.PrjOrderID, checkResult ? EnumResult.成功 : EnumResult.失败, true);
                                                                }
                                                            }
                                                            #endregion
                                                        }));
                                    break;
                            }

                            threadMethod[j].Start();
                        }
                        System.Threading.Tasks.Task.WaitAll(threadMethod.Where((t) => t != null).ToArray());
                        for (int k = 0; k < this.threadMethod.Length; k++)
                        {
                            try
                            {
                                if (threadMethod[k] != null)
                                    threadMethod[k].Dispose();
                            }
                            catch
                            {
                            }
                            finally
                            {
                                threadMethod[k] = null;
                            }
                        }
                    }
                }
                if (Item.PrjType != EnumFAType.密钥下装) break;

                if (intDownKeyStep++ == 0 && CallBackKeyDownStepFunction != null) //第一步完成
                {

                    string message = "";

                    for (int bno = 0; bno < MeterItems.Count; bno++)
                    {
                        if (MeterItems[bno].CheckYn && MeterItems[bno].getPrjResult(Item.PrjOrderID, false) == EnumResult.成功)
                        {
                            MeterItems[bno].SetPrjResult(Item.PrjOrderID, EnumResult.进行中, false);

                            if (MeterItems[bno].MControl.IsInCode)
                            {
                                message += string.Format("【{0}】", MeterItems[bno].MeterBwh);
                            }
                        }
                    }

                    if (CallBackKeyDownStepFunction(message))
                    {
                        continue;
                    }
                    else
                    { break; }

                }
                else
                {
                    intDownKeyStep = 0;
                    break;
                }
            }
        }
    }
}
